#include "StdAfx.h"
#include "FFEXMBLHandler.h"
#include "Utils/Logger.h"
#include "Utils/FastBlockQueue.h"
#include "Business/PendingMarket.h"

using namespace std;

FFEXMblHandler::FFEXMblHandler(FastBlockQueue& queue,ContractCodes const& contractCodes) 
:m_queue(queue),m_pMblApi(NULL),m_contractCodes(contractCodes)
{
	for (UINT i = 0; i < m_contractCodes.size(); ++i)
	{
		Variety const& contract = m_contractCodes[i];
		m_contractIndexMap[contract.GetCode()] = i;
	}
}

void FFEXMblHandler::OnFrontConnected()
{
	CThostFtdcReqUserLoginField reqUserLogin; 
	strcpy_s(reqUserLogin.BrokerID, "3040"); 
	strcpy_s(reqUserLogin.UserID, "dongzheng01"); 
	strcpy_s(reqUserLogin.Password,"cjhyy"); 
	m_pMblApi->ReqUserLogin(&reqUserLogin, 1);
}

void FFEXMblHandler::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	UNREFERENCED_PARAMETER(bIsLast);
	UNREFERENCED_PARAMETER(nRequestID);
	UNREFERENCED_PARAMETER(pRspUserLogin);

	if (pRspInfo == NULL && pRspInfo->ErrorID != 0)
	{
		LightLogger::Error(FT("MblHandler OnRspUserLogin failed,code[%d]",pRspInfo->ErrorID));
	}
	else
	{
		LightLogger::Info(FT("MblHandler OnRspUserLogin success"));
	}
}

void FFEXMblHandler::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	UNREFERENCED_PARAMETER(bIsLast);
	UNREFERENCED_PARAMETER(nRequestID);
	if (pRspInfo == NULL)
	{
		LightLogger::Warn(FT("MblHandlerOnRspError pRspInfo is null"));
	}
	else
	{
		LightLogger::Warn(FT("MblHandler OnRspError code[%d],msg[%s]",pRspInfo->ErrorID,pRspInfo->ErrorMsg));
	}
}

void FFEXMblHandler::OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField *pInstrumentStatus)
{
	if (pInstrumentStatus == NULL)
	{
		return;
	}
	LightLogger::Info(FT("%s status[%c]",pInstrumentStatus->InstrumentID,pInstrumentStatus->InstrumentStatus));
}

void FFEXMblHandler::OnRtnMBLMarketData(CThostFtdcBaseMBLMarketDataField *pBaseMBLMarketData)
{
	if (pBaseMBLMarketData == NULL)
	{
		return;
	}
	int contractIndex = GetContractIndex(pBaseMBLMarketData->InstrumentID);
	if (contractIndex < 0)
	{
		return;
	}
	QueueItem item = {0};
	item.type = QueueItem::PENDING_MARKET;
	PendingMarket& pendingMarket = *(PendingMarket*)item.data;
	pendingMarket.contract = contractIndex;
	pendingMarket.direction = pBaseMBLMarketData->Direction == THOST_FTDC_D_Buy ? Direction::BUY : Direction::SELL ;
	pendingMarket.price = int(pBaseMBLMarketData->Price);
	pendingMarket.quantity = int(pBaseMBLMarketData->Volume);
	m_queue.Push(item);

// 	LightLogger::Info(FT("MBL Market [%s] direction[%c] price[%.2f] position[%d]",
// 		pBaseMBLMarketData->InstrumentID,pBaseMBLMarketData->Direction,	pBaseMBLMarketData->Price,pBaseMBLMarketData->Volume));
}

void FFEXMblHandler::OnRspSubMBLMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	UNREFERENCED_PARAMETER(bIsLast);
	UNREFERENCED_PARAMETER(nRequestID);
	if (pRspInfo != NULL && pRspInfo->ErrorID != 0)
	{
		LightLogger::Info(FT("SubMblMarket Failed,[%d][%s]",pRspInfo->ErrorID,pRspInfo->ErrorMsg));
	}
	if (pSpecificInstrument != NULL)
	{
		LightLogger::Info(FT("Sub MblMarket Success,[%d]",pSpecificInstrument->InstrumentID));
	}
}

void FFEXMblHandler::Subscribe(char const* code)
{
	LightLogger::Info(FT("subscribing [%s] pending market",code));

	m_codes.push_back(code);
	char* pCodes[400] = {0};

	for (size_t i = 0; i < m_codes.size(); ++i)
	{
		pCodes[i] = (char*)m_codes[i].c_str();
	}

	int ret = m_pMblApi->SubscribeMBLMarketData(pCodes,m_codes.size());
#ifndef LOG4CPLUS_DISABLE_DEBUG
	LightLogger::Debug(FT("Mbl SubscribeMarketData return [%d]",ret));
#endif
}

int FFEXMblHandler::GetContractIndex(char const* instrumentID)
{
	map<string,int>::const_iterator iter = m_contractIndexMap.find(instrumentID);
	if (iter == m_contractIndexMap.end())
	{
		// receive not exist contract market,log it and return
#ifndef LOG4CPLUS_DISABLE_DEBUG
		LightLogger::Debug(FT("InstrumentId[%s] can't find contractIndex",instrumentID));
#endif
		return -1;
	}
	return iter->second;
}
